package com.yummy.web.security.filter;

import java.io.IOException;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.util.AntPathMatcher;

import com.yummy.web.security.config.FilterPattern;

public abstract class AbstractSecurityFilter implements Filter{
	
	private AntPathMatcher matcher = new AntPathMatcher();
	
	private FilterPattern filterPattern;
	
	public AbstractSecurityFilter(FilterPattern filterPattern) {
		this.setFilterPattern(filterPattern);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException{
		if(!shouldFilter(request,response)) {
			chain.doFilter(request, response);
			return;
		}
		if(accessAllowed(request,response)) {
			chain.doFilter(request, response);
			return;
		}
		sendAccessDenied(request,response);
	}

	protected abstract void sendAccessDenied(ServletRequest request, ServletResponse response);

	protected abstract boolean accessAllowed(ServletRequest request, ServletResponse response);

	protected boolean shouldFilter(ServletRequest request, ServletResponse response) {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String path = getRequestPath(httpRequest);
		return include(path) || !exclude(path);
	}
	
	private boolean exclude(String path) {
		return filterPattern != null 
				&& filterPattern.getExcludes() != null 
				&& match(filterPattern.getExcludes(),path);
	}

	private boolean include(String path) {
		return filterPattern != null 
				&& filterPattern.getIncludes() != null 
				&& match(filterPattern.getIncludes(),path);
	}
	private boolean match(List<String> patterns, String path) {
		if(patterns == null) {
			return false;
		}
		for(String pattern : patterns) {
			if(matcher.match(pattern, path)) {
				return true;
			}
		}
		return false;
	}

	protected String getRequestPath(HttpServletRequest request) {
		String url = request.getServletPath();

		if (request.getPathInfo() != null) {
			url += request.getPathInfo();
		}

		return url;
	}

	public FilterPattern getFilterPattern() {
		return filterPattern;
	}

	public void setFilterPattern(FilterPattern filterPattern) {
		this.filterPattern = filterPattern;
	}

}
